//convert .xlsx to .csv
//todo:optimize .csv file size(kick off the double quote)
package main

import (
	"bufio"
	"bytes"
	"encoding/binary"
	"flag"

	"hash/adler32"
	"runtime/debug"
	// "bufio"
	"encoding/csv"
	"io/ioutil"

	// "encoding/csv"
	"errors"
	"fmt"
	"github.com/tealeg/xlsx"
	"os"
	"path/filepath"
	// "path/filepath"
)

// "github.com/tealeg/xlsx"
// "io"
func Adler32Dir(dir string) {
	filePaths, err := ioutil.ReadDir(dir)

	if err != nil {
		fmt.Println("read dir:", dir, " error:", err)
		return
	}
	var totalBuf bytes.Buffer
	for _, fInfo := range filePaths {
		// fInfo, err := os.Stat(dir + "/" + fPath.Name())
		// if err != nil {
		// 	fmt.Println(err)
		// 	continue
		// }

		if fInfo.IsDir() {
			continue
		}

		f, err := os.Open(dir + "/" + fInfo.Name())
		if err != nil {
			fmt.Println(err)
			continue
		}

		rd := bufio.NewReader(f)
		totalBuf.ReadFrom(rd)
		f.Close()
		// os.Open(fPath)
		// fmt.Println(totalBuf.Bytes())
	}

	adler := adler32.Checksum(totalBuf.Bytes())
	adlerFile, err := os.Create(dir + "/adler")
	binary.Write(adlerFile, binary.LittleEndian, adler)
	adlerFile.Close()

	if err != nil {
		fmt.Println(err)
	}
}

var SpecifyDir = flag.String("d", "", "Specify Diretory")
var WorkDir = flag.String("w", "", "workDir Diretory")

func main() {

	defer func() {
		// c.Close()
		if pn := recover(); pn != nil {
			fmt.Println(" panic:", pn, "\n stack:", string(debug.Stack()))
		} else {
			fmt.Print("Convert finish\\o/. ")
		}
		// fmt.Println("press Enter to continue.")
		// bufio.NewReader(os.Stdin).ReadByte()
	}()
	flag.Parse()

	// allTbl = make(map[string]*GDTable)
	workDir, err := filepath.Abs(filepath.Dir(os.Args[0]))

	if err != nil {
		fmt.Println(err)
	}

	if len(*WorkDir) != 0 {
		workDir = *WorkDir

	}
	// _, err = os.Stat(workDir + "/csv")
	// fmt.Println(err)
	// bufio.NewReader(os.Stdin).ReadByte()
	// // os.Mkdir(workDir+"/csv", os.ModeDir)
	// return
	// fmt.Println(workDir)

	filePaths, _ := ioutil.ReadDir(workDir)
	csvDir := workDir + "/csv"
	//fmt.Println("*SpecifyDir:", *SpecifyDir)
	if len(*SpecifyDir) != 0 {
		csvDir = *SpecifyDir

	}

	for _, f := range filePaths {

		// fmt.Println()
		// fmt.Println(f.Name())
		fName := f.Name()
		extName := filepath.Ext(fName)
		bName := fName[:len(fName)-len(extName)]

		if extName == ".xlsx" {
			// fmt.Print(os.Stat(csvDir))
			_ = bName
			if _, err := os.Stat(csvDir); err != nil {
				os.Mkdir(workDir+"/csv", os.ModeDir)
				// fmt.Println("Mkdir")
			}

			Convert(workDir+"/"+f.Name(), csvDir)
		}
		//

	}
	Adler32Dir(csvDir)
	// fmt.Println("Convert finish\\o/. \npress Enter to continue.")
	// bufio.NewReader(os.Stdin).ReadByte()
}

func Convert(xlsxPath string, csvDir string) error {

	if len(xlsxPath) == 0 {
		return errors.New("no read file.")
	}

	if filepath.Ext(xlsxPath) != ".xlsx" {
		return errors.New("extend not right")
	}

	if _, err := os.Stat(filepath.Dir(csvDir)); err != nil {
		return err
	}
	fmt.Println(filepath.Base(xlsxPath))
	xlFile, err := xlsx.OpenFile(xlsxPath)
	if err != nil {
		fmt.Println(err)
	}

	for _, sheet := range xlFile.Sheets {

		if sheet.MaxCol == 0 || sheet.MaxRow == 0 {
			continue
		}

		//find out maxcol, sheet.MaxCol not right!
		maxCol := 0
		for _, row := range sheet.Rows {
			if len(row.Cells) > maxCol {
				maxCol = len(row.Cells)
			}
		}
		csvStrs := make([][]string, sheet.MaxRow)
		// fmt.Println("sheet.MaxRow:", sheet.MaxRow, "  sheet.MaxCol:", sheet.MaxCol)
		for iRow, row := range sheet.Rows {
			csvStrs[iRow] = make([]string, maxCol)
			// fmt.Println("len(row.Cells):", len(row.Cells))

			for iCol, cell := range row.Cells {
				// fmt.Println("iCol", iCol, "iRow", "iRow")
				csvStrs[iRow][iCol] = cell.String()
			}
		}

		csvF, err := os.Create(csvDir + "/" + sheet.Name + ".csv")
		if err != nil {
			return err
		}
		csvWriter := csv.NewWriter(csvF)
		csvWriter.WriteAll(csvStrs)

		//read test
		// csvReader := csv.NewReader(csvF)
		// _, err := csvReader.ReadAll()

		// if err != nil {
		// 	fmt.Println("csv:", sheet.Name, " error:", err)
		// 	continue
		// }
	}
	return nil
}
